home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / asm_n_z.zip / WAITASEC.ASM < prev    next >
Assembly Source File  |  1986-02-05  |  15KB  |  450 lines

  1. ;    WAITASEC.ASM -- Holds and Recalls Scrolling Screens
  2. ;    ============
  3. ;            (C) Copyright Charles Petzold, 1985
  4. ;
  5. ;            COM file format
  6. ;
  7.  
  8. CSEG        Segment
  9.         Assume    CS:CSEG
  10.         Org    0080h
  11. SWAP        Label    Byte        ; Use this area for line swapping
  12.         Org    0100h
  13. Entry:        Jmp    Initialize    ; Entry: Jump over resident part
  14.  
  15. ;    All Data
  16. ;    --------
  17.  
  18. Cols        equ    80        ; You may want to set this to 40
  19. ScrollLock    equ    70        ; Scan code of Scroll Lock key
  20. NumberOfScreens    dw    8        ; Can be set up to 15 for 80-column
  21.  
  22.         db    '(C) Copyright Charles Petzold, 1985'
  23.  
  24. DisplaySegment    dw    ?        ; Display address set by VideoCheck
  25. OldInterrupt9    dd    ?         ; Saved address of real Interrupt 9
  26. OldInterrupt10    dd    ?        ; Ditto for Interrupt 10h
  27.  
  28. TopHoldAddr    dw    Offset HoldArea    ; Address of top of Hold area
  29. BotHoldAddr    dw    ?        ; Address of bottom of Hold area
  30. SavePointer    dw    Offset HoldArea ; Points to where text is saved
  31. RecallPointer    dw    Offset HoldArea    ; Points to where text is recalled
  32.  
  33. LockStateOn    db    0        ; Flag for lock or no lock
  34. ScrollLockDown    db    0        ; Current state of Scroll Lock key
  35.  
  36. KeyDispatch    dw    Home,Up,PgUp    ; Dispatch addresss of routines
  37.         dw    5 Dup (Dummy)    ; for cursor movement within
  38.         dw    End,Down,PgDn    ; recalled displays
  39.  
  40. ;    Intercept of Interrupt 10h -- BIOS Video Call
  41. ;    --------------------------
  42.  
  43. NewInterrupt10:    Cmp    AX,0601h    ; Check if this is a 1 line scroll up
  44.         Jne    NoNeedToBother    ; No, just continue to real interrupt
  45.         Cmp    CX,0        ; Check if this is upper left corner
  46.         Jne    NoNeedToBother    ; No, don't want to touch it
  47.         Cmp    DL,Cols - 1    ; Check if DL is right hand side
  48.         Jne    NoNeedToBother    ; Another obstacle that shuts us out    
  49.         Call    VideoCheck    ; Returns Carry if graphics
  50.         Jc    NoNeedToBother    ; So we drop out here if Carry is set
  51.  
  52.         Sti            ; Allow interrupts
  53.         Cld            ; And set direction to forward
  54.         Push    CX        ; Save all the registers we'll use 
  55.         Push    SI
  56.         Push    DI
  57.         Push    DS
  58.         Push    ES
  59.  
  60.         Push    CS            ; Push this code segment
  61.         Pop    ES            ; So we can set ES to it
  62.         Mov    DI,CS:[SavePointer]    ; This is the destination
  63.         Mov    DS,CS:[DisplaySegment]    ; This is the source segment
  64.         Sub    SI,SI            ; Source is top of display
  65.         Mov    CX,Cols            ; The number of characters
  66.  
  67.         Call    VideoOff        ; Turn off light show if color
  68.         Rep    Movsw            ; Move 'em in!
  69.         Call    VideoOn            ; Turn display back on
  70.  
  71.         Cmp    DI,CS:[BotHoldAddr]    ; Check the new destination
  72.         Jb    NotAtBotYet        ; Jump if it hasn't wrapped yet
  73.         Mov    DI,CS:[TopHoldAddr]    ; Set it to top if it has
  74. NotAtBotYet:    Mov    CS:[SavePointer],DI    ; And save it anyway
  75.         
  76.         Pop    ES            ; Pop the registers we saved 
  77.         Pop    DS
  78.         Pop    DI
  79.         Pop    SI
  80.         Pop    CX
  81.  
  82. NoNeedToBother:    Jmp    CS:[OldInterrupt10]    ; And do the interrupt for real
  83.  
  84. ;    Intercept of Interrupt 9h -- Hardware Keyboard Interrupt
  85. ;    --------------------------------------------------------    
  86.  
  87. NewInterrupt9:    Sti            ; Allow other interrupts
  88.         Push    AX        ; Save the register for awhile
  89.         In    AL,60h        ; Get the pressed key scan code
  90.         Cmp    AL,ScrollLock    ; Check if it's the Scroll Lock
  91.         Jz    GottaScrollLock    ; If so, do special routine
  92.         Cmp    AL,128 + ScrollLock    ; Check if scroll lock release
  93.         Jz    ScrollLockRlse    ; Another special routine
  94.         Jmp    AnyOtherKey    ; Otherwise, it's some other key
  95.  
  96.                         ; Scroll Lock key depressed
  97.                         ; -------------------------
  98.  
  99. GottaScrollLock:Mov    CS:[ScrollLockDown],1    ; Flag Scroll Lock as depressed
  100.         Cmp    CS:[LockStateOn],1    ; See if we're locked now
  101.         Jz    AnyOtherKey        ; If so, will just reset
  102.  
  103.         Mov    AH,2            ; Do keyboard interrupt
  104.         Int    16h            ;   to get shift states
  105.         Test    AL,04            ; See if Ctrl has been pressed
  106.         Jnz    NormalProcess        ; Process normally if Break
  107.  
  108.         Call    VideoCheck        ; See if video is OK for recall
  109.         Jc    NormalProcess        ; If not, ignore the key
  110.  
  111.         Mov    CS:[LockStateOn],1    ; Lock state now ON
  112.         Push    CS:[SavePointer]    ; Transfer value of SavePointer
  113.         Pop    CS:[RecallPointer]    ; ... to RecallPointer 
  114.         PushF                ; Simulate an interrupt
  115.         Call    CS:[OldInterrupt9]    ; Let Scroll Lock Register
  116.         Call    VideoOn            ; Video might be off - turn on
  117.  
  118. HoldingPattern:    Cmp    CS:[LockStateOn],1    ; Wait in this loop ...
  119.         Jz    HoldingPattern        ; ... until out of lock state 
  120.  
  121.         Jmp    NormalProcess        ; Then process last key
  122.  
  123.                         ; Scroll Lock key released
  124.                         ; ------------------------
  125.  
  126. ScrollLockRlse:    Mov    CS:[ScrollLockDown],0    ; Register Scroll Lock release
  127.         Cmp    CS:[LockStateOn],1    ; See if in lock state
  128.         Jnz    NormalProcess        ; If not, just process key
  129.  
  130.         Mov    AX,CS:[SavePointer]    ; Check if the screen is in
  131.         Cmp    AX,CS:[RecallPointer]    ;   normal position
  132.         Jnz    NormalProcess        ; If not, just process key
  133.  
  134.         Mov    CS:[LockStateOn],0    ; If so, turn lock state OFF
  135.         Pop    AX            ; Restore register
  136.         IRet                ; Return to holding pattern
  137.  
  138.                         ; All other keys
  139.                         ; --------------
  140.  
  141. AnyOtherKey:    Cmp    CS:[LockStateOn],1    ; For other keys, just do
  142.         Jnz    NormalProcess        ; normal processing if not lock
  143.  
  144.         Call    NowInLockState        ; But call routine if locked
  145.         Pop    AX            ; Restore register
  146.         IRet                ; Return to holding pattern
  147.  
  148. NormalProcess:    Pop    AX            ; Get back the register
  149.         Jmp    CS:[OldInterrupt9]    ; Let the key process
  150.  
  151. ;    Routine for other keys during lock state (AL = Scan Code)
  152. ;    ---------------------------------------------------------
  153.  
  154. NowInLockState:    Cld            ; String moves generally forward
  155.         Push    CX        ; We use all these registers
  156.         Push    DX
  157.         Push    SI 
  158.         Push    DI
  159.         Push    DS
  160.         Push    ES
  161.  
  162.         Mov    DX,CS            ; Get value of CS    
  163.         Mov    DS,DX            ; Set DS and
  164.         Mov    ES,DX            ; ES to this segment
  165.         Assume    DS:CSEG, ES:CSEG    ; And tell the assembler     
  166.  
  167.         Mov    AH,AL            ; AH is actual scan code
  168.         And    AL,7Fh            ; AL has release byte off
  169.  
  170.         Sub    AL,71            ; Subtract the 'Home' key value
  171.         Jb    WrongKey        ; No good if below
  172.         Cmp    AL,(81 - 71)        ; Above the 'PgDn' key?
  173.         Ja    WrongKey        ; You're not right either
  174.         Cmp    AL,(73 - 71)        ; Check if under or = 'PgUp'
  175.         Jbe    AllRightKey        ; Ok for this key
  176.         Cmp    AL,(79 - 71)        ; Check if over or = 'End'
  177.         Jae    AllRightKey        ; You pass too
  178.  
  179. WrongKey:    Cmp    [ScrollLockDown],1    ; See if scroll lock is down
  180.         Jz    ResetKeyboard        ; If so, just ignore the key
  181.  
  182.         Call    End            ; If not, restore the display
  183.         Mov    [LockStateOn],0        ; Turn off the lock state
  184.         Jmp    KeyReturn        ; And get out quickly    
  185.  
  186. AllRightKey:    Test    AH,80h            ; See if cursor key is release
  187.         Jnz    ResetKeyboard        ; If so, ignore the key
  188.  
  189.         Cbw                ; Convert scan code to word    
  190.         Add    AX,AX            ; Double it because word access
  191.         Mov    SI,AX            ; Set SI to it
  192.         Call    [KeyDispatch + SI]    ; And do the routine
  193.  
  194. ResetKeyboard:    In    AL,61h            ; These instructions
  195.         Mov    AH,AL            ; reset the keyboard
  196.         Or    AL,80h
  197.         Out    61h,AL
  198.         Mov    AL,AH
  199.         Out    61h,AL
  200.  
  201.         Cli                ; Disable interrupts
  202.         Mov    AL,20h            ; to reset the interrupt
  203.         Out    20h,AL            ; controller
  204.         
  205. KeyReturn:    Pop    ES            ; Get back all the pushes
  206.         Pop    DS
  207.         Pop    DI
  208.         Pop    SI
  209.         Pop    DX
  210.         Pop    CX
  211.         Ret                ; Return to previous routine
  212.  
  213. ;    Routines to scan up through saved display
  214. ;    -----------------------------------------
  215.  
  216. Home:        Mov    CX,0FFFFh    ; 'Home' key -- "infinite" lines up
  217.         Jmp    Short GoingUp    ; Do it
  218.  
  219. Up:        Mov    CX,1        ; 'Up' key -- 1 line up
  220.         Jmp    Short GoingUp    ; Go to it
  221.  
  222. PgUp:        Mov    CX,25        ; 'PgUp' key -- 25 lines (1 screen) up    
  223.  
  224. GoingUp:    Mov    AX,[RecallPointer]    ; Points to the text source
  225.         Cmp    AX,[TopHoldAddr]    ; Check if it's at the top
  226.         Ja    NotScanUpTop        ; If not there, no problem
  227.         Mov    AX,[BotHoldAddr]    ; Otherwise must wrap around
  228. NotScanUpTop:    Sub    AX,Cols * 2        ; Go back one line for recall
  229.         Cmp    AX,[SavePointer]    ; Check if cycled through yet
  230.         Je    EndGoingUp        ; If so, abort this routine
  231.  
  232.         Mov    [RecallPointer],AX    ; Save the new pointer value
  233.         Push    CX            ; And save our counter
  234.  
  235.         Mov    SI,2 * 24 * Cols    ; Set source to bottom line
  236.         Call    DisplayToSwap        ; Transfer it to SWAP area 
  237.     
  238.         Mov    SI,2 * 24 * Cols - 2    ; End of penultimate line 
  239.         Mov    DI,2 * 25 * Cols - 2    ; End of last line
  240.         Std                ; Backwards string transfer
  241.         Call    ScrollDisplay        ; Do the screen scroll
  242.         Cld                ; Direction back to forward
  243.  
  244.         Mov    DI,0            ; Destination is top line
  245.         Call    HoldToDisplay        ; Move line to display
  246.         Call     SwapToHold        ; And SWAP line to hold
  247.  
  248.         Pop    CX            ; Get back the counter
  249.         Loop    GoingUp            ; And do CX time